home *** CD-ROM | disk | FTP | other *** search
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Ink;
- using System.Windows.Threading;
- using System.IO;
- using System.Windows.Media;
-
- namespace UntitledProject1
- {
- public enum RepeatMode
- {
- Once,
- Loop,
- Bounce
- }
-
- /// <summary>
- /// INotifyPropertyChanged allows that properties of the Class InkPen
- /// participate as source in data bindings.
- /// </summary>
- public class FlipBook : INotifyPropertyChanged
- {
- /// <summary>
- /// INotifyPropertyChanged requires a property called PropertyChanged.
- /// </summary>
- public event PropertyChangedEventHandler PropertyChanged;
-
- // Empty content to be returned, in case the frame index is out of range.
- private static StrokeCollection EmptyStrokeCollection = new StrokeCollection();
-
- // There are three options for repeatMode:
- // Once - Plays the animations one time.
- // Loop - Play in a infinite loop.
- // Bounce - Plays and reverses the animation in an infinite loop.
- private RepeatMode repeatMode = RepeatMode.Loop;
-
- // Timer that controls the player.
- private DispatcherTimer timer = null;
-
- // Direction of the animation: 1 = play, 0 = paused, -1 = reverse.
- private int playDirection = 0;
-
- private ObservableCollection<StrokeCollection> frames = new ObservableCollection<StrokeCollection>();
- private int currentIndex = 0;
- private int framesPerSecond = 10;
-
- #region Initialization
-
- public FlipBook()
- {
- Setup();
- }
-
- public FlipBook(int frameCount)
- {
- if (frameCount < 1)
- {
- frameCount = 1;
- }
- for (int i = 0; i < frameCount; i++)
- {
- this.frames.Add(new StrokeCollection());
- }
- Setup();
- }
-
- public void Setup()
- {
- // DelegateCommand allows drag & drop of commands to controls as
- // a CLR Object Data Source under Data in the Project Panel.
- playCommand = new DelegateCommand(delegate() { Play(); });
- pauseCommand = new DelegateCommand(delegate() { Pause(); });
- newCommand = new DelegateCommand(delegate() { Clear(); });
- newFrameCommand = new DelegateCommand(delegate() { CreateNewFrame(); });
- cloneFrameCommand = new DelegateCommand(delegate() { CloneCurrentFrame(); });
- removeFrameCommand = new DelegateCommand(delegate() { RemoveCurrentFrame(); });
- nextFrameCommand = new DelegateCommand(delegate() { NextFrame(); });
- previousFrameCommand = new DelegateCommand(delegate() { PreviousFrame(); });
- firstFrameCommand = new DelegateCommand(delegate() { FirstFrame(); });
- lastFrameCommand = new DelegateCommand(delegate() { LastFrame(); });
-
- // Initializes Drawing Attributes
- drawAtt = new DrawingAttributes();
- drawAtt.FitToCurve = true;
- drawAtt.Color = Colors.Black;
- w = 9;
- drawAtt.Width = w;
- drawAtt.Height = w;
-
- // Register the attributes to raise an event when the property changes.
- OnPropertyChanged("InkColor");
- OnPropertyChanged("InkWidth");
- OnPropertyChanged("InkAttributes");
-
- // Creates the first empty frame.
- CreateNewFrame();
- }
-
- #endregion
-
- #region Attributes
-
- public ICollection<StrokeCollection> Frames
- {
- get { return this.frames; }
- }
-
- public int CurrentIndex
- {
- get { return this.currentIndex; }
- set
- {
- if (value >= this.frames.Count)
- {
- value = this.frames.Count - 1;
- }
- else if (value < 0)
- {
- value = 0;
- }
- this.currentIndex = value;
-
- // Sends notification that the following properties have changed.
- this.OnPropertyChanged("CurrentIndex");
- this.OnPropertyChanged("CurrentFrame");
- this.OnPropertyChanged("PreviousFrame1");
- this.OnPropertyChanged("PreviousFrame2");
- this.OnPropertyChanged("PreviousFrame3");
- }
- }
-
- public StrokeCollection CurrentFrame
- {
- get
- {
- if (this.currentIndex >= 0 && this.currentIndex < this.frames.Count)
- {
- return this.frames[this.currentIndex];
- }
- return EmptyStrokeCollection;
- }
- }
-
- public StrokeCollection PreviousFrame1
- {
- get
- {
- int index = this.currentIndex - 1;
- if (index >= 0 && index < this.frames.Count)
- {
- return this.frames[index];
- }
- return EmptyStrokeCollection;
- }
- }
-
- public StrokeCollection PreviousFrame2
- {
- get
- {
- int index = this.currentIndex - 2;
- if (index >= 0 && index < this.frames.Count)
- {
- return this.frames[index];
- }
- return EmptyStrokeCollection;
- }
- }
-
- public StrokeCollection PreviousFrame3
- {
- get
- {
- int index = this.currentIndex - 3;
- if (index >= 0 && index < this.frames.Count)
- {
- return this.frames[index];
- }
- return EmptyStrokeCollection;
- }
- }
-
- public RepeatMode RepeatMode
- {
- get { return this.repeatMode; }
- set
- {
- if (this.repeatMode != value)
- {
- this.repeatMode = value;
- this.OnPropertyChanged("RepeatMode");
-
- if (this.playDirection == -1 && value != RepeatMode.Bounce)
- {
- this.playDirection = 1;
- }
- }
- }
- }
-
- private Color color;
-
- public Color InkColor
- {
- get { return color; }
- set { color = value; OnPropertyChanged("InkColor"); UpdateAtt(); }
- }
-
- private double w;
-
- public double InkWidth
- {
- get { return w; }
- set { w = value; OnPropertyChanged("InkWidth"); UpdateAtt(); }
- }
-
- private DrawingAttributes drawAtt;
-
- public DrawingAttributes InkAttributes
- {
- get { return drawAtt; }
- }
-
- public int FramesPerSecond
- {
- get { return this.framesPerSecond; }
- set
- {
- if (this.framesPerSecond != value)
- {
- this.framesPerSecond = value;
- if (this.timer != null)
- {
- this.timer.Interval = TimeSpan.FromMilliseconds(1000 / this.framesPerSecond);
- }
- this.OnPropertyChanged("FramesPerSecond");
- }
- }
- }
-
- public bool IsPlaying
- {
- get { return this.timer != null; }
- set
- {
- if (this.IsPlaying != value)
- {
- if (value)
- {
- this.Play();
- }
- else
- {
- this.Pause();
- }
- }
- }
- }
-
- #endregion
-
- #region Frames
-
- public void CreateNewFrame()
- {
- this.frames.Add(new StrokeCollection());
- this.CurrentIndex = this.frames.Count - 1;
- }
-
- public void CloneCurrentFrame()
- {
- this.frames.Add(this.CurrentFrame.Clone());
- this.CurrentIndex = this.frames.Count - 1;
- }
-
- public void RemoveCurrentFrame()
- {
- if (this.frames.Count > 1)
- {
- this.CurrentFrame.Clear();
- this.frames.Remove(this.CurrentFrame);
- }
- else
- {
- this.CurrentFrame.Clear();
- this.CurrentIndex = 0;
- }
- }
-
- public void Play()
- {
- if (!this.IsPlaying)
- {
- this.playDirection = 1;
- TimeSpan timeSpan = TimeSpan.FromMilliseconds(1000 / this.framesPerSecond);
- this.timer = new DispatcherTimer(timeSpan, DispatcherPriority.Normal, new EventHandler(this.PlayNextFrame), Dispatcher.CurrentDispatcher);
- this.timer.Start();
- this.OnPropertyChanged("IsPlaying");
- }
- else
- {
- Pause();
- }
- }
-
- public void Pause()
- {
- if (this.IsPlaying)
- {
- this.playDirection = 0;
- this.timer.Stop();
- this.timer = null;
-
- this.OnPropertyChanged("IsPlaying");
- }
- }
-
- private void PlayNextFrame(object sender, EventArgs e)
- {
- if (this.playDirection == 1 && this.currentIndex == this.frames.Count - 1)
- {
- // When the player reaches the end of the animation, check what is the current repeatMode option.
- switch (this.repeatMode)
- {
- case RepeatMode.Once:
- // Pause.
- this.Pause();
- break;
- case RepeatMode.Loop:
- // Restart at the first frame.
- this.currentIndex = -1;
- break;
- case RepeatMode.Bounce:
- // Reverse direction.
- this.playDirection = -1;
- break;
- }
- }
- else if (this.playDirection == -1 && this.currentIndex == 0)
- {
- if (this.repeatMode == RepeatMode.Bounce)
- {
- this.playDirection = 1;
- }
- else
- {
- this.Pause();
- }
- }
- this.CurrentIndex += this.playDirection;
- }
-
- public void Clear()
- {
- this.Pause();
- this.frames = new ObservableCollection<StrokeCollection>();
- this.frames.Add(new StrokeCollection());
- this.currentIndex = 0;
- this.OnAllPropertiesChanged();
- }
-
- public void NextFrame() { this.CurrentIndex++; }
- public void PreviousFrame() { this.CurrentIndex--; }
- public void FirstFrame() { this.CurrentIndex = 0; }
- public void LastFrame() { this.CurrentIndex = this.Frames.Count - 1; }
-
- #endregion
-
- #region File
-
- /// <summary>
- /// Saves the animation as a collection of Strokes.
- /// The method StrokeCollection.Save allows saving stroke binary data.
- /// </summary>
- public void Save(string path)
- {
- FileStream writer = new FileStream(path, FileMode.Create);
- writer.WriteByte((byte)this.repeatMode);
- writer.WriteByte((byte)this.framesPerSecond);
- foreach (StrokeCollection collection in this.Frames)
- {
- collection.Save(writer);
- }
- writer.Close();
- }
-
- public void Load(string path)
- {
- this.Pause();
- FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read);
- RepeatMode newRepeatMode = (RepeatMode)reader.ReadByte();
- int newFramesPerSecond = reader.ReadByte();
- ObservableCollection<StrokeCollection> newFrames = new ObservableCollection<StrokeCollection>();
- while (reader.Position < reader.Length)
- {
- newFrames.Add(new StrokeCollection(reader));
- }
- reader.Close();
-
- // Only replace the current animation if we successfully read the whole file.
- this.repeatMode = newRepeatMode;
- this.framesPerSecond = newFramesPerSecond;
- this.frames = newFrames;
- this.currentIndex = 0;
- this.OnAllPropertiesChanged();
- }
-
- #endregion
-
- #region Property Change
-
- /// <summary>
- /// Fires the event for the property when it changes.
- /// </summary>
- private void OnPropertyChanged(string propertyName)
- {
- if (this.PropertyChanged != null)
- {
- // In order to INotifyPropertyChanged to work it is necessary
- // that the property fires the event whenever it changes.
- this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
-
- private void OnAllPropertiesChanged()
- {
- this.OnPropertyChanged("Frames");
- this.OnPropertyChanged("CurrentIndex");
- this.OnPropertyChanged("CurrentFrame");
- this.OnPropertyChanged("PreviousFrame1");
- this.OnPropertyChanged("PreviousFrame2");
- this.OnPropertyChanged("PreviousFrame3");
- this.OnPropertyChanged("RepeatMode");
- this.OnPropertyChanged("FramesPerSecond");
- this.OnPropertyChanged("InkColor");
- this.OnPropertyChanged("InkWidth");
- this.OnPropertyChanged("InkAttributes");
- }
-
- /// <summary>
- /// Updates the Pen attributes
- /// </summary>
- private void UpdateAtt()
- {
- drawAtt.Color = color;
- drawAtt.Width = w;
- drawAtt.Height = w;
- OnPropertyChanged("InkAttributes");
- }
-
- #endregion
-
- #region Delegate Commands
-
- private DelegateCommand playCommand;
- private DelegateCommand pauseCommand;
- private DelegateCommand newCommand;
- private DelegateCommand newFrameCommand;
- private DelegateCommand cloneFrameCommand;
- private DelegateCommand removeFrameCommand;
- private DelegateCommand nextFrameCommand;
- private DelegateCommand previousFrameCommand;
- private DelegateCommand firstFrameCommand;
- private DelegateCommand lastFrameCommand;
-
-
- public DelegateCommand PlayCommand { get { return playCommand; } }
- public DelegateCommand PauseCommand { get { return pauseCommand; } }
- public DelegateCommand NewCommand { get { return newCommand; } }
- public DelegateCommand NewFrameCommand { get { return newFrameCommand; } }
- public DelegateCommand CloneFrameCommand { get { return cloneFrameCommand; } }
- public DelegateCommand RemoveFrameCommand { get { return removeFrameCommand; } }
- public DelegateCommand NextFrameCommand { get { return nextFrameCommand; } }
- public DelegateCommand PreviousFrameCommand { get { return previousFrameCommand; } }
- public DelegateCommand FirstFrameCommand { get { return firstFrameCommand; } }
- public DelegateCommand LastFrameCommand { get { return lastFrameCommand; } }
-
- #endregion
-
- }
-
- }
-